﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace Web.Ajax.Data
{
	using Hashtable = System.Collections.Hashtable;

	public class Xml : System.Collections.Hashtable
	{
		public System.Collections.Hashtable xmlns = new System.Collections.Hashtable();
		public string Namespace;

		public string Name;

		public bool ClosingTagRequired;

		public string FullTagName
		{
			get
			{
				if (!string.IsNullOrEmpty(Namespace))
					return Namespace + ":" + Name;
				return Name;
			}
		}

		public string Content;

		public bool InheritNamespace = true;

		public List<Xml> Children = new List<Xml>();

		public Xml(string name)
		{
			Name = name;
		}

		public Xml(string name, string content) : this(name)
		{
			Content = content;
		}

		public void Add(Xml node)
		{
			Children.Add(node);
		}

		public void Add(IEnumerable<Xml> nodes)
		{
			Children.AddRange(nodes);
		}

		public void AddTag(string name, string content)
		{
			Add(new Xml(name, content));
		}
		public void AddTag(string name)
		{
			Add(new Xml(name));
		}

		public class Attribute
		{
			public string Name;
			public string Value;

			public string GetXml()
			{
				if (Value == null)
					return null;
				return Name + "=\"" + Value + "\"";
			}
		}

		public string GetXml(int ind)
		{
			var children = new List<Xml>();
			children.AddRange(Children);
			var attributes = new List<Attribute>();
			foreach (var k in Keys)
			{
				var o = this[k];
				if (o == null)
					continue;
				var t = o.GetType();
				if(t==typeof(List<Xml>))
				{
					var l = (List<Xml>)o;
					foreach (var x in l)
						children.Add(x);
					continue;
				}
				if (t == typeof(Xml[]))
				{
					var l = (Xml[])o;
					foreach (var x in l)
						children.Add(x);
					continue;
				}
				if (t == typeof(Xml))
				{
					children.Add((Xml)o);
					continue;
				}
				attributes.Add(new Attribute() { Name = k.ToString(), Value = ((string)this[k]) });
			}

			var xml = new StringBuilder();
			for (var i = 0; i < ind; i++)
				xml.Append("\t");

			var tabstring = xml.ToString();

			xml.Append("<" + FullTagName);
			if (xmlns != null)
			{
				foreach (var k in xmlns.Keys)
				{
					var ns = xmlns[k];
					if(ns !=null && ns is string)
						xml.Append(" xmlns:" + k+"=\""+xmlns[k]+"\"");
				}
			}
			foreach (var a in attributes)
			{
				xml.Append(" " + a.GetXml());
			}
			if (children.Count == 0 && string.IsNullOrEmpty(Content) && !ClosingTagRequired)
			{
				xml.Append("/>");
				return xml.ToString();
			}
			xml.Append(">");

			foreach (var c in children)
			{
				if (c.InheritNamespace)
					c.Namespace = Namespace;
				xml.Append("\r\n" + c.GetXml(ind + 1));
			}
			xml.Append(Content);
			xml.Append("\r\n"+tabstring+"</" + FullTagName + ">");
			return xml.ToString();
		}

		public string GetXml()
		{
			return GetXml(0);
		}

		public string GetXmlDoc()
		{
			var xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
			xml.Append(GetXml(0));
			return xml.ToString();
		}
	}
}
